package com.tkjt.pms.calc.core;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import com.tkjt.pms.calc.IndexCalcDependecyService;
import com.tkjt.pms.calc.KpiCalculator;
import com.tkjt.pms.calc.common.CalcResult;
import com.tkjt.pms.calc.common.IndexCalcConsts;
import com.tkjt.pms.calc.common.IndexCalcSerial;
import com.tkjt.pms.calc.utils.EsCalcUtils;
import com.tkjt.pms.common.IndexConsts;
import com.tkjt.pms.common.utils.EsDateUtils;
import com.tkjt.pms.server.IndexServer;
import com.tkjt.pms.server.ServerService;
import com.tkjt.pms.server.common.ServerParam;
import com.tkjt.pms.server.common.ServerTask;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service("kpiIndexsCalculator")
public class KpiCalculatorImpl implements KpiCalculator {

	@Autowired
	private IndexCalcDependecyService indexCalcDependecyService;

	@Autowired
	private IndexServer indexServer;

	@Qualifier(KpiCalculator.SERVICE_CALC_SERVER)
	@Autowired
	private ServerService serverService;
	
	@Autowired
	private CalcStatusWatcher calcStatusWatcher;
	
	

	@Override
	public CalcResult<String> doCalculator(String dataType, String indexYearMonth, Set<String> indexGroups) {
		
		CalcResult<String> calcResult = new CalcResult<String>();
		
		if(calcStatusWatcher.haveCalcOngoing(dataType, indexYearMonth, indexGroups)) {
			calcResult.error("计算任务正在执行中,稍后再试......");
			return calcResult;
		} else {
			calcStatusWatcher.doWatcher(dataType, indexYearMonth, indexGroups);
		}

		Date calcTimeStart = new Date();
		// 给出默认计算月份
		if (StringUtils.isEmpty(indexYearMonth)) {
			indexYearMonth = EsDateUtils.getLastMonthStr(new Date());
		}
		String calcCode = EsCalcUtils.getCBatchCode(indexYearMonth);
		log.info("calculator indexYearMonth={}, calcCode={}", indexYearMonth, calcCode);

		// 此List不可并行计算,对计算有先后次序要求 ===> 串行
		List<IndexCalcSerial> indexCalcSerials = indexCalcDependecyService.loadIndexCalcDependencies(dataType, indexYearMonth, indexGroups);
		log.info("indexCalcSerial size={}", indexCalcSerials.size());
		Date calcTimeDepen = new Date();

		List<ServerTask> serverTasks = new ArrayList<ServerTask>();
		for (IndexCalcSerial calcSerial : indexCalcSerials) {
			ServerParam params = new ServerParam();
			// 业务执行类
			params.setServerServiceName(KpiCalculator.SERVICE_CALC_SERVER);
			// 任务执行参数
			params.addParam(IndexConsts.PARAM_INDEX_YEAR_MONTH, indexYearMonth);
			params.addParam(IndexConsts.PARAM_INDEX_CALC_SERIAL, calcSerial);
			params.addParam(IndexCalcConsts.PARAM_CALC_CBATCH_CODE, calcCode);
			params.addParam(IndexCalcConsts.PARAM_SERVER_TYPE, ServerParam.SERVER_TYPE_SINGLE);
			// 分析辅助信息
			params.addParam(IndexCalcConsts.PARAM_CALC_TIME_START, calcTimeStart);
			params.addParam(IndexCalcConsts.PARAM_CALC_TIME_DEPEN, calcTimeDepen);

			ServerTask oneTask = new ServerTask(params);
			serverTasks.add(oneTask);
		}

		indexServer.doIndexServer(serverTasks);
		log.info("add server task, size={}", serverTasks.size());
		
		return calcResult;
	}

	@Override
	public CalcResult<String> doCalculator(String dataType, String indexYearMonth, String indexGroup, Set<String> indexValueCodes, Set<String> indexDeparts) {

		CalcResult<String> calcResult = new CalcResult<String>();
		
		if(calcStatusWatcher.haveCalcOngoing(dataType, indexYearMonth, indexGroup)) {
			calcResult.error("计算任务正在执行中,稍后再试......");
			return calcResult;
		} else {
			calcStatusWatcher.doWatcher(dataType, indexYearMonth, indexGroup);
		}
		
		Date calcTimeStart = new Date();
		// 给出默认计算月份
		if (StringUtils.isEmpty(indexYearMonth)) {
			indexYearMonth = EsDateUtils.getLastMonthStr(new Date());
		}
		String calcCode = EsCalcUtils.getCBatchCode(indexYearMonth);
		log.info("calculator indexYearMonth={}, calcCode={}", indexYearMonth, calcCode);

		// 此List不可并行计算,对计算有先后次序要求 ===> 串行
		List<IndexCalcSerial> indexCalcSerials = indexCalcDependecyService.loadIndexCalcDependencies(dataType, indexYearMonth, indexGroup, indexValueCodes, indexDeparts);
		log.info("indexCalcSerial size={}", indexCalcSerials.size());
		Date calcTimeDepen = new Date();

		List<ServerTask> serverTasks = new ArrayList<ServerTask>();
		for (IndexCalcSerial calcSerial : indexCalcSerials) {
			ServerParam params = new ServerParam();
			// 业务执行类
			params.setServerServiceName(KpiCalculator.SERVICE_CALC_SERVER);
			params.setServerType(ServerParam.SERVER_TYPE_SINGLE);
			// 任务执行参数
			params.addParam(IndexConsts.PARAM_INDEX_YEAR_MONTH, indexYearMonth);
			params.addParam(IndexConsts.PARAM_INDEX_CALC_SERIAL, calcSerial);
			// 分析辅助信息
			params.addParam(IndexCalcConsts.PARAM_CALC_CBATCH_CODE, calcCode);
			params.addParam(IndexCalcConsts.PARAM_CALC_TIME_START, calcTimeStart);
			params.addParam(IndexCalcConsts.PARAM_CALC_TIME_DEPEN, calcTimeDepen);

			ServerTask oneTask = new ServerTask(params);
			serverTasks.add(oneTask);
		}

		indexServer.doIndexServer(serverTasks);
		log.info("add server task, size={}", serverTasks.size());
		
		return calcResult;
	}

	@Override
	public CalcResult<String> doCalculatorDirectly(String dataType, String indexYearMonth, String indexGroup, String indexValueCode, String whichDepart) {

		CalcResult<String> calcResult = new CalcResult<String>();		
		if(calcStatusWatcher.haveCalcOngoing(dataType, indexYearMonth, indexGroup)) {
			calcResult.error("计算任务正在执行中,稍后再试......");
			return calcResult;
		}
		
		String calcCode = EsCalcUtils.getCBatchCode(indexYearMonth);
		log.info("start calculator directly, cbatch code={}", calcCode);
		Date calcTimeStart = new Date();
		List<IndexCalcSerial> indexCalcSerials = null;
		indexCalcSerials = indexCalcDependecyService.loadIndexCalcDependencies(dataType, indexYearMonth, indexGroup, indexValueCode, whichDepart);
		Date calcTimeDepen = new Date();
		log.info("load index calc dependencies done.");
		for (IndexCalcSerial indexCalcSerial : indexCalcSerials) {
			ServerParam params = new ServerParam();
			params.addParam(IndexConsts.PARAM_INDEX_YEAR_MONTH, indexYearMonth);
			params.addParam(IndexConsts.PARAM_INDEX_CALC_SERIAL, indexCalcSerial);
			// 分析辅助信息
			params.addParam(IndexCalcConsts.PARAM_CALC_CBATCH_CODE, calcCode);
			params.addParam(IndexCalcConsts.PARAM_CALC_TIME_START, calcTimeStart);
			params.addParam(IndexCalcConsts.PARAM_CALC_TIME_DEPEN, calcTimeDepen);
			serverService.doService(params);
		}
		log.info("end calculator, cbatch cdoe={}", calcCode);
		
		return calcResult;
	}

}
